package com.atguigu.tingshu.order.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.account.AccountFeignClient;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.delay.DelayMsgService;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.order.OrderDerate;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.VipServiceConfig;
import com.atguigu.tingshu.order.helper.SignHelper;
import com.atguigu.tingshu.order.mapper.OrderDerateMapper;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.account.AccountLockVo;
import com.atguigu.tingshu.vo.order.OrderDerateVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.atguigu.tingshu.vo.order.TradeVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

/**
 * 订单信息服务iml
 *
 * @author ym
 * @date 2025/06/28 22:07
 */
@Slf4j
@Service
@SuppressWarnings({"all"})
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private AccountFeignClient accountFeignClient;

    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AlbumFeignClient albumFeignClient;
    @Autowired
    private OrderDerateMapper orderDerateMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private DelayMsgService delayMsgService;

    /**
     * 贸易
     *
     * @param tradeVo 贸易组织
     * @return {@link OrderInfoVo}
     */
    @Override
    public OrderInfoVo trade(Long userId, TradeVo tradeVo) {
        //创建OrderInfoVo对象
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        //设置orderinfoVo对象的属性
        String itemType = tradeVo.getItemType();
        //1.1 订单信息VO封装-购买项目类型
        orderInfoVo.setItemType(itemType);
        BigDecimal originalAmount = new BigDecimal("0.00");
        BigDecimal derateAmount = new BigDecimal("0.00");
        BigDecimal orderAmount = new BigDecimal("0.00");
        ArrayList<OrderDetailVo> orderDetailVos = new ArrayList<>();
        ArrayList<OrderDerateVo> orderDerateVos = new ArrayList<>();
        if (itemType.equals(SystemConstant.ORDER_ITEM_TYPE_VIP)) {
            // 会员
            log.info("会员");
            VipServiceConfig vipServiceConfig = userFeignClient.getVipServiceConfig(tradeVo.getItemId()).getData();
            if (vipServiceConfig != null) {
                log.info("会员服务配置：{}", vipServiceConfig);
                originalAmount = vipServiceConfig.getPrice();
                orderAmount = vipServiceConfig.getDiscountPrice();
                derateAmount = originalAmount.subtract(orderAmount);
                OrderDetailVo orderDetailVo = new OrderDetailVo();
                orderDetailVo.setItemId(tradeVo.getItemId());
                orderDetailVo.setItemName(vipServiceConfig.getName());
                orderDetailVo.setItemUrl(vipServiceConfig.getImageUrl());
                orderDetailVo.setItemPrice(orderAmount);
                orderDetailVos.add(orderDetailVo);
                OrderDerateVo orderDerateVo = new OrderDerateVo();
                orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_VIP_SERVICE_DISCOUNT);
                orderDerateVo.setDerateAmount(derateAmount);
                orderDerateVo.setRemarks("会员服务优惠" + derateAmount);
                orderDerateVos.add(orderDerateVo);


            }

        } else if (itemType.equals(SystemConstant.ORDER_ITEM_TYPE_ALBUM)) {
            // 专辑
            Long albumId = tradeVo.getItemId();
            //查看是否购买过
            Boolean bolean = userFeignClient.getalbumisPaidorNot(albumId).getData();
            if (bolean) {
                //如果购买过,直接报错显示已购买
                throw new GuiguException(400, "该专辑已购买");
            } else {
                AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(albumId).getData();

                //初始价格不变
                originalAmount = albumInfo.getPrice();
                BigDecimal discount = albumInfo.getDiscount();
                //查看客户是否是vip如果是就按会员价计算折扣信息如果不是就按普通会员价计算折扣信息
                Boolean flag = userFeignClient.getUserIsVipOrNot(albumId).getData();
                if (flag) {
                    BigDecimal vipDiscount = albumInfo.getVipDiscount();
                    if (vipDiscount.compareTo(new BigDecimal("-1")) == 0) {
                        orderAmount = BigDecimal.valueOf(0);
                    } else {
                        orderAmount = originalAmount.multiply(vipDiscount).multiply(BigDecimal.valueOf(0.1)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        ;
                    }

                } else {
                    if (discount.compareTo(new BigDecimal("-1")) == 0) {
                        orderAmount = BigDecimal.valueOf(0);
                    } else {
                        //得出最终价格
                        orderAmount = originalAmount.multiply(discount).multiply(BigDecimal.valueOf(0.1)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        ;
                    }

                }
                derateAmount = originalAmount.subtract(orderAmount);
                //如果没购买过,查询专辑详情,计算订单金额
                OrderDetailVo orderDetailVo = new OrderDetailVo();
                orderDetailVo.setItemName(albumInfo.getAlbumTitle());
                orderDetailVo.setItemUrl(albumInfo.getCoverUrl());
                orderDetailVo.setItemPrice(orderAmount);
                orderDetailVo.setItemId(albumId);
                orderDetailVos.add(orderDetailVo);
                OrderDerateVo orderDerateVo = new OrderDerateVo();
                if (derateAmount.intValue() > 0) {
                    orderDerateVo.setDerateAmount(derateAmount);
                    orderDerateVo.setRemarks("专辑优惠" + derateAmount);

                    orderDerateVo.setDerateType(SystemConstant.ORDER_DERATE_ALBUM_DISCOUNT);
                    orderDerateVos.add(orderDerateVo);
                }
            }

            log.info("专辑");
        } else if (itemType.equals(SystemConstant.ORDER_ITEM_TYPE_TRACK)) {
            //当前trackId
            Long trackId = tradeVo.getItemId();
            AlbumInfo albumInfo = albumFeignClient.getAlbumInfobytrackId(trackId).getData();
            //购买数量,如果有购买过的进行顺延
            Integer trackCount = tradeVo.getTrackCount();
            //根据声音id获取专辑id所对应的专辑下的声音列表
            List<TrackInfo> data = albumFeignClient.getavalibleTrackIfo(trackId, trackCount).getData();
            for (TrackInfo trackInfo : data) {
                OrderDetailVo orderDetailVo = new OrderDetailVo();
                orderDetailVo.setItemId(trackInfo.getId());
                orderDetailVo.setItemName(trackInfo.getTrackTitle());
                orderDetailVo.setItemUrl(albumInfo.getCoverUrl());
                orderDetailVo.setItemPrice(albumInfo.getPrice());
                orderDetailVos.add(orderDetailVo);
            }
            originalAmount = albumInfo.getPrice().multiply(new BigDecimal(data.size()));

            orderAmount = originalAmount;

            // 课程
            log.info("单曲");
        }
        orderInfoVo.setOrderDetailVoList(orderDetailVos);
        orderInfoVo.setOrderDerateVoList(orderDerateVos);
        orderInfoVo.setOriginalAmount(originalAmount);
        orderInfoVo.setDerateAmount(derateAmount);
        orderInfoVo.setOrderAmount(orderAmount);
        //5.1 本次结算流水号-防止重复提交
        //5.1.1 构建当前用户本次订单流水号Key
        String tradeNoKey = RedisConstant.ORDER_TRADE_NO_PREFIX + userId;//存入redis的 key
        //订单号
        String tradeNo = IdUtil.fastSimpleUUID();
        orderInfoVo.setTradeNo(tradeNo);
        //5.1.2 存入redis
        //6.1 订单信息VO封装-订单信息
        redisTemplate.opsForValue().set(tradeNoKey, tradeNo, 5, TimeUnit.MINUTES);
        orderInfoVo.setTradeNo(tradeNo);
        orderInfoVo.setTimestamp(DateUtil.current());
        Map<String, Object> paramMap = BeanUtil.beanToMap(orderInfoVo, false, true);
        String sign = SignHelper.getSign(paramMap);
        orderInfoVo.setSign(sign);

        return orderInfoVo;
    }

    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> submitOrder(Long userId, OrderInfoVo orderInfoVo) {

        //查看订单类型

        String tradeNoKey = RedisConstant.ORDER_TRADE_NO_PREFIX + userId;//存入redis的 key
        String tradeNo = orderInfoVo.getTradeNo();
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                "return redis.call('del', KEYS[1]) " +
                "else " +
                "return 0 " +
                "end";
        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(script);
        redisScript.setResultType(Boolean.class);
        Boolean execute = (Boolean) redisTemplate.execute(redisScript, List.of(tradeNoKey), tradeNo);
        if (!execute) {
            throw new GuiguException(400, "订单重复提交");
        }

        //防止订单重复提交
        //防止篡改订单

        Map<String, Object> paramMap = BeanUtil.beanToMap(orderInfoVo);
        paramMap.remove("payWay");
        SignHelper.checkSign(paramMap);
        //订单校验完毕,进行保存订单
        OrderInfo orderInfo = this.saveOrder(orderInfoVo, userId);
        //查看支付方式
        String payWay = orderInfoVo.getPayWay();
        if (SystemConstant.ORDER_PAY_ACCOUNT.equals(payWay)) {
            AccountLockVo accountLockVo = new AccountLockVo();
            accountLockVo.setOrderNo(orderInfo.getOrderNo());
            accountLockVo.setAmount(orderInfo.getOrderAmount());
            accountLockVo.setUserId(userId);
            accountLockVo.setContent(orderInfo.getOrderTitle());

            Result result = accountFeignClient.checkAndLock(accountLockVo);
            if (result.getCode() != 200) {
                throw new GuiguException(400, result.getMessage());
            }
            UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
            userPaidRecordVo.setOrderNo(orderInfo.getOrderNo());
            userPaidRecordVo.setUserId(userId);
            userPaidRecordVo.setItemType(orderInfo.getItemType());
            List<Long> list = orderInfoVo.getOrderDetailVoList().stream()
                    .map(orderDetailVo -> orderDetailVo.getItemId()).toList();
            userPaidRecordVo.setItemIdList(list);
            //发货行为
            Result result1 = userFeignClient.addUserPaidRecord(userPaidRecordVo);
            if (result1.getCode() != 200) {
                throw new GuiguException(400, "发货异常");
            }
            orderInfo.setOrderStatus(SystemConstant.ORDER_STATUS_PAID);
            orderInfo.setUpdateTime(new Date());
            orderInfo.setPayWay(SystemConstant.ORDER_PAY_ACCOUNT);

            orderInfoMapper.updateById(orderInfo);//进行修改
        }

        //设置延迟关单
        delayMsgService.sendDelayMsg(KafkaConstant.QUEUE_ORDER_CANCEL, orderInfo.getOrderNo(),
                10L);

        return Map.of("orderNo", orderInfo.getOrderNo());
    }

    @Override
    public OrderInfo saveOrder(OrderInfoVo orderInfoVo, Long userId) {
        //保存订单

        OrderInfo orderInfo = BeanUtil.copyProperties(orderInfoVo, OrderInfo.class);
        orderInfo.setUserId(userId);
        String itemName = orderInfoVo.getOrderDetailVoList().get(0).getItemName();
        orderInfo.setOrderTitle(itemName);
        String orderNo = DateUtil.today().replaceAll("-", "") + IdUtil.fastSimpleUUID();
        orderInfo.setOrderNo(orderNo);
        //设置订单状态为未支付
        orderInfo.setOrderStatus(SystemConstant.ORDER_STATUS_UNPAID);


        orderInfoMapper.insert(orderInfo);
        //保存详情
        List<OrderDerateVo> orderDerateVoList = orderInfoVo.getOrderDerateVoList();
        for (OrderDerateVo orderDerateVo : orderDerateVoList) {

            OrderDerate orderDerate = BeanUtil.copyProperties(orderDerateVo, OrderDerate.class);
            orderDerate.setOrderId(orderInfo.getId());
            orderDerateMapper.insert(orderDerate);
        }
        List<OrderDetailVo> orderDetailVoList = orderInfoVo.getOrderDetailVoList();
        for (OrderDetailVo orderDetailVo : orderDetailVoList) {
            OrderDetail orderDetail = BeanUtil.copyProperties(orderDetailVo, OrderDetail.class);
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }
        return orderInfo;
    }

    @Override
    public OrderInfo getOrderInfo(Long userId, String orderNo) {
        QueryWrapper<OrderInfo> eq = new QueryWrapper<OrderInfo>()
                .eq("user_id", userId).eq("order_no", orderNo);
        OrderInfo orderInfo = orderInfoMapper.selectOne(eq);
        List<OrderDetail> orderDetailVos = new ArrayList<>();
        List<OrderDerate> orderDerateVos = new ArrayList<>();
        if (orderInfo != null) {
            return getInfo(orderInfo);
        }
        return null;

    }

    private OrderInfo getInfo(OrderInfo orderInfo) {
        List<OrderDetail> orderDetailVos;
        List<OrderDerate> orderDerateVos;
        QueryWrapper<OrderDetail> orderDetailQueryWrapper = new QueryWrapper<>();
        orderDetailQueryWrapper.eq("order_id", orderInfo.getId());
        orderDetailVos = orderDetailMapper.selectList(orderDetailQueryWrapper);
        QueryWrapper<OrderDerate> orderDerateQueryWrapper = new QueryWrapper<>();
        orderDerateQueryWrapper.eq("order_id", orderInfo.getId());
        orderDerateVos = orderDerateMapper.selectList(orderDerateQueryWrapper);
        orderInfo.setOrderDetailList(orderDetailVos);
        orderInfo.setOrderDerateList(orderDerateVos);
        String payWay = orderInfo.getPayWay();
        String s = this.setOrderStatusName(orderInfo.getOrderStatus());
        String payWayName = this.getPayWayName(orderInfo.getPayWay());
        orderInfo.setOrderStatusName(s);
        orderInfo.setPayWayName(payWayName);
        return orderInfo;
    }

    private String getPayWayName(String payWay) {
        if (payWay.equals(SystemConstant.ORDER_PAY_ACCOUNT)) {

            return "余额支付";
        } else if (payWay.equals(SystemConstant.ORDER_PAY_WAY_WEIXIN)) {

            return "微信支付";
        } else if (payWay.equals(SystemConstant.ORDER_PAY_WAY_ALIPAY)) {

            return "支付宝支付";
        }
        return null;
    }

    @Override
    public Page<OrderInfo> findUserPage(Long userId, Integer pageNum, Integer limit) {

        Page<OrderInfo> page = new Page<>(pageNum, limit);
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        orderInfoQueryWrapper.eq("user_id", userId);
        orderInfoQueryWrapper.orderByDesc("create_time");
        Page<OrderInfo> orderInfoPage = orderInfoMapper.selectPage(page, orderInfoQueryWrapper);
        List<OrderInfo> records = orderInfoPage.getRecords();
        for (OrderInfo orderInfo : records) {
            getInfo(orderInfo);
        }
        return orderInfoPage;
    }

    @Override
    public void orderCancal(String orderNo) {
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        orderInfoQueryWrapper.eq("order_no", orderNo);
        OrderInfo orderInfo = orderInfoMapper.selectOne(orderInfoQueryWrapper);
        if (orderInfo!=null&&orderInfo.getOrderStatus().equals(SystemConstant.ORDER_STATUS_UNPAID)) {
            orderInfo.setOrderStatus(SystemConstant.ORDER_STATUS_CANCEL);
            orderInfo.setUpdateTime(new Date());
            orderInfoMapper.updateById(orderInfo);
        }
    }

    private String setOrderStatusName(String orderStatus) {
        if (orderStatus.equals(SystemConstant.ORDER_STATUS_UNPAID)) {
            return "未支付";
        } else if (orderStatus.equals(SystemConstant.ORDER_STATUS_PAID)) {
            return "已支付";
        } else if (orderStatus.equals(SystemConstant.ORDER_STATUS_CANCEL)) {
            return "已取消";
        }
        return null;
    }
}


